﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;                        //INI引用
using System.Runtime.InteropServices;   //INI引用
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;     //TCP IP
using System.Net;             //TCP IP
using System.Collections;     //TCP IP
using System.IO.Ports; //使用串口
using System.Text.RegularExpressions;  //使用串口

namespace WZS_Package
{
    class OperateIniFile
    {
       ////////////////////////////////////////////////////////////////////////////////////////
         #region API函数声明

        [DllImport("kernel32")]//返回0表示失败，非0为成功
        private static extern long WritePrivateProfileString(string section,string key,
            string val,string filePath);

        [DllImport("kernel32")]//返回取得字符串缓冲区的长度
        private static extern long GetPrivateProfileString(string section,string key,
            string def,StringBuilder retVal,int size,string filePath);

        #endregion

        #region 读Ini文件

        public static string ReadIniData(string Section,string Key,string NoText,string iniFilePath)
        {
            if(File.Exists(iniFilePath))
            {
                StringBuilder temp = new StringBuilder(1024);
                GetPrivateProfileString(Section,Key,NoText,temp,1024,iniFilePath);
                return temp.ToString();
            }
            else
            {
                return String.Empty;
            }
        }

        #endregion

        #region 写Ini文件

        public static bool WriteIniData(string Section,string Key,string Value,string iniFilePath)
        {
            if(File.Exists(iniFilePath))
            {
                long OpStation = WritePrivateProfileString(Section,Key,Value,iniFilePath);    
                if(OpStation == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            else
            {
                return false;
            }
        }

        #endregion

    //////////////////////////////////////////////////////////////////////////////////////////
    }


    class ComPortCommunication
    {
        SerialPort port1;  //串口
        StringBuilder builder = new StringBuilder();  //避免在事件处理方法中反复的创建，定义到外面
        public string ReceiveData = "";//接收到的数据
        public bool DisplayHex = false;//是否以16进制显示

        public void ComPortOpen(string portName, int baudRate)
        {
            if (port1 != null && port1.IsOpen)
            {
                port1.Close();                //打开时点击，则关闭串口
            }
            try
            {
                port1 = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);//创建串口 //初始化SerialPort对象
                port1.NewLine = "\r\n";//根据实际情况吧。
                //添加事件注册
                port1.DataReceived += ComPortDataReceived;
                port1.Open();
                port1.DiscardInBuffer();
                port1.DiscardOutBuffer();
            }
            catch (Exception ex)
            {
                //捕获到异常信息，创建一个新的comm对象，之前的不能用了。
                port1 = new SerialPort();
                //现实异常信息给客户。
                throw new Exception(ex.Message);
            }
        }
        public void ComPortOpen(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
        {
            if (port1 != null && port1.IsOpen)
            {
                port1.Close();                //打开时点击，则关闭串口
            }
            try
            {
                port1 = new SerialPort(portName, baudRate, parity, dataBits, stopBits);//创建串口 //初始化SerialPort对象
                port1.NewLine = "\r\n";//根据实际情况吧。
                //添加事件注册
                port1.DataReceived += ComPortDataReceived;
                port1.Open();
                port1.DiscardInBuffer();
                port1.DiscardOutBuffer();
            }
            catch (Exception ex)
            {
                //捕获到异常信息，创建一个新的comm对象，之前的不能用了。
                port1 = new SerialPort();
                //现实异常信息给客户。
                throw new Exception(ex.Message);
            }
        }
        public void ComPortDataSend(string senddata, bool SendHex, bool NewLine)
        {
            if (SendHex)
            {
                MatchCollection mc = Regex.Matches(senddata, @"(?i)[\da-f]{2}");
                List<byte> buf = new List<byte>();
                foreach (Match m in mc)
                {
                    buf.Add(byte.Parse(m.Value, System.Globalization.NumberStyles.HexNumber));
                }
                port1.Write(buf.ToArray(), 0, buf.Count);
            }
            else
            {
                if (NewLine)
                {
                    port1.WriteLine(senddata);
                }
                else
                {
                    port1.Write(senddata);
                }
            }
        }
        private void ComPortDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(50);//确保数据接收完成
            int n = port1.BytesToRead;//先记录下来，避免某种原因，人为的原因，操作几次之间时间长，缓存不一致
            byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
            port1.Read(buf, 0, n);//读取缓冲数据
            builder.Clear();//清除字符串构造器的内容           
            //判断是否是显示为16进制
            if (DisplayHex)
            {
                //依次的拼接出16进制字符串
                foreach (byte b in buf)
                {
                    builder.Append(b.ToString("X2") + " ");
                }
            }
            else
            {
                //直接按ASCII规则转换成字符串
                builder.Append(Encoding.ASCII.GetString(buf));
            }
            ReceiveData = builder.ToString();
        }
        public void ComPortClose()
        {
            if (port1 != null && port1.IsOpen)
            {
                port1.Close();                //打开时点击，则关闭串口
            }
        }

        private byte[] CRC16_C(byte[] data)  //CRC16校验
        {
            byte CRC16Lo;
            byte CRC16Hi;   //CRC寄存器 
            byte CL; byte CH;       //多项式码&HA001 
            byte SaveHi; byte SaveLo;
            byte[] tmpData;
            int I;
            int Flag;
            CRC16Lo = 0xFF;
            CRC16Hi = 0xFF;
            CL = 0x01;
            CH = 0xA0;
            tmpData = data;
            for (int i = 0; i < tmpData.Length; i++)
            {
                CRC16Lo = (byte)(CRC16Lo ^ tmpData[i]); //每一个数据与CRC寄存器进行异或 
                for (Flag = 0; Flag <= 7; Flag++)
                {
                    SaveHi = CRC16Hi;
                    SaveLo = CRC16Lo;
                    CRC16Hi = (byte)(CRC16Hi >> 1);      //高位右移一位 
                    CRC16Lo = (byte)(CRC16Lo >> 1);      //低位右移一位 
                    if ((SaveHi & 0x01) == 0x01) //如果高位字节最后一位为1 
                    {
                        CRC16Lo = (byte)(CRC16Lo | 0x80);   //则低位字节右移后前面补1 
                    }             //否则自动补0 
                    if ((SaveLo & 0x01) == 0x01) //如果LSB为1，则与多项式码进行异或 
                    {
                        CRC16Hi = (byte)(CRC16Hi ^ CH);
                        CRC16Lo = (byte)(CRC16Lo ^ CL);
                    }
                }
            }
            byte[] ReturnData = new byte[2];
            ReturnData[0] = CRC16Hi;       //CRC高位 
            ReturnData[1] = CRC16Lo;       //CRC低位 
            return ReturnData;
        }
        public string StrAddCRC(string str, byte device_num)
        {
            char[] aa = str.ToCharArray();
            int num = aa.Length + 9;
            byte[] bb = new byte[num];
            bb[0] = 0xFF;
            bb[1] = 0xFF;
            bb[2] = 0xFF;
            bb[3] = 0xFF;
            bb[4] = device_num;
            bb[5] = 0x20;
            bb[6] = 0x00;
            bb[7] = 0x00;
            bb[8] = Convert.ToByte(str.Length);
            for (int i = 0; i < str.Length; i++)
            {
                bb[9 + i] = Convert.ToByte(aa[i]);
            }
            byte[] cc = CRC16_C(bb);
            byte[] dd = new byte[num + 2];
            for (int i = 0; i < num; i++)
            {
                dd[i] = bb[i];
            }
            dd[num] = cc[1];
            dd[num + 1] = cc[0];
            string sendstr = "";
            for (int i = 0; i < num + 2; i++)
            {
                sendstr = sendstr + dd[i].ToString("X2") + " ";
            }
            return sendstr;
        }

    }
    class TcpIpCommunication
    {
        private Thread ServerThread;//服务器
        private string S_ServerIp = "127.0.0.1"; private int S_port = 1000;//服务器IP，端口
        private Socket s, temp;
        private bool ServerListen = false;
        private Thread ClientThread;//客户端
        private string C_ClientIp = "127.0.0.1"; private int C_ClientPort = 1000;//客户端Ip ，端口
        private TcpClient client = null;
        private NetworkStream sendStream = null;
        private bool ClientConnect = false;
        public string S_ReceiveData = "", C_ReceiveData = "";//服务器接收数据，客户端接收数据

        public void OpenServer(string ServerIp, int Serverport)
        {
            S_ServerIp = ServerIp;
            S_port = Serverport;
            if (temp != null && !temp.Poll(0, SelectMode.SelectRead))//是否连接成功
            { temp.Close(); temp = null; }
            if (s != null)
            { s.Close(); s = null; }
            if (ServerThread != null && ServerThread.IsAlive)
            { ServerThread.Abort(); ServerThread = null; }
            ServerThread = new Thread(new ThreadStart(ServerReceiveData));
            ServerThread.IsBackground = true;//将线程设为后台线程
            ServerThread.Start();
        }
        public void ServerReceiveData()
        {
            try
            {
                IPAddress ip = IPAddress.Parse(S_ServerIp);     //创建终结点
                IPEndPoint ipe = new IPEndPoint(ip, S_port);
                s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket对象，如果用UDP协议，则要用SocketTyype.Dgram类型的套接字
                s.Bind(ipe);    //绑定EndPoint对象(2000端口和ip地址)
                s.Listen(0);    //开始监听,等待客户端连接
                ServerListen = true;
                while (ServerListen)
                {
                    try
                    {
                        temp = s.Accept();   //为新建立的连接创建新的Socket
                        while (temp != null && !temp.Poll(0, SelectMode.SelectRead))//是否连接成功
                        {
                            byte[] recvBytes = new byte[1024];
                            int bytes = temp.Receive(recvBytes, recvBytes.Length, 0); //从客户端接受消息
                            S_ReceiveData = Encoding.ASCII.GetString(recvBytes, 0, bytes);
                        }
                    }
                    catch
                    {
                        break;
                    }
                }
            }
            catch
            {
                return;
            }
        }
        public void ServerSendData(string sendStr)
        {
            if (temp != null && !temp.Poll(0, SelectMode.SelectRead))//是否连接成功
            {
                byte[] bs = Encoding.ASCII.GetBytes(sendStr);
                temp.Send(bs, bs.Length, 0);  //返回信息给客户端
            }
        }
        public void CloseServer()
        {

            ServerListen = false;
            if (temp != null && !temp.Poll(0, SelectMode.SelectRead))//是否连接成功
            { temp.Close(); temp = null; }
            if (s != null)
            { s.Close(); s = null; }
            if (ServerThread != null && ServerThread.IsAlive)
            { ServerThread.Abort(); ServerThread = null; }
        }
        public bool Check_Client_State()
        {
            if (temp != null && !temp.Poll(0, SelectMode.SelectRead))//是否连接成功
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public void OpenClient(string ClientIp, int ClientPort)
        {
            C_ClientIp = ClientIp;
            C_ClientPort = ClientPort;
            if (sendStream != null)
                sendStream.Close();
            if (client != null)
                client.Close();
            if (ClientThread != null && ClientThread.IsAlive)
                ClientThread.Abort();
            ClientThread = new Thread(new ThreadStart(ClientReceiveData));
            ClientThread.IsBackground = true;//将线程设为后台线程
            ClientThread.Start();
        }
        public void ClientReceiveData()
        {
            try
            {
                ClientConnect = true;
                while (ClientConnect)
                {
                    client = new TcpClient(C_ClientIp, C_ClientPort);
                    sendStream = client.GetStream();
                    try
                    {
                        while (client.Connected)
                        {
                            byte[] bytes = new byte[1024];
                            int bytesread = sendStream.Read(bytes, 0, bytes.Length);
                            C_ReceiveData = Encoding.Default.GetString(bytes, 0, bytesread);
                            sendStream.Flush();
                        }
                    }
                    catch
                    {
                        break;
                    }
                }
            }
            catch
            {

                return;
            }
        }
        public void ClientSendData(String msg)
        {
            Byte[] sendBytes = Encoding.Default.GetBytes(msg);
            sendStream.Write(sendBytes, 0, sendBytes.Length);
        }
        public void CloseClient()
        {
            ClientConnect = false;
            if (sendStream != null)
            { sendStream.Close(); sendStream = null; }
            if (client != null)
            { client.Close(); client = null; }
            if (ClientThread != null && ClientThread.IsAlive)
            { ClientThread.Abort(); ClientThread = null; }
        }
        public bool Check_Server_State()
        {
            if (client.Connected)
            {
                return true;
            }
            else
            {

                return false;
            }
        }

    }
   
}
